// -*- C++ -*-
//===------------------------ type_traits ---------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES.
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCUDACXX_TYPE_TRAITS
#define _LIBCUDACXX_TYPE_TRAITS

/*
    type_traits synopsis

namespace std
{

    // helper class:
    template <class T, T v> struct integral_constant;
    typedef integral_constant<bool, true>  true_type;   // C++11
    typedef integral_constant<bool, false> false_type;  // C++11

    template <bool B>                                   // C++14
    using bool_constant = integral_constant<bool, B>;   // C++14
    typedef bool_constant<true> true_type;              // C++14
    typedef bool_constant<false> false_type;            // C++14

    // helper traits
    template <bool, class T = void> struct enable_if;
    template <bool, class T, class F> struct conditional;

    // Primary classification traits:
    template <class T> struct is_void;
    template <class T> struct is_null_pointer;  // C++14
    template <class T> struct is_integral;
    template <class T> struct is_floating_point;
    template <class T> struct is_array;
    template <class T> struct is_pointer;
    template <class T> struct is_lvalue_reference;
    template <class T> struct is_rvalue_reference;
    template <class T> struct is_member_object_pointer;
    template <class T> struct is_member_function_pointer;
    template <class T> struct is_enum;
    template <class T> struct is_union;
    template <class T> struct is_class;
    template <class T> struct is_function;

    // Secondary classification traits:
    template <class T> struct is_reference;
    template <class T> struct is_arithmetic;
    template <class T> struct is_fundamental;
    template <class T> struct is_member_pointer;
    template <class T> struct is_scalar;
    template <class T> struct is_object;
    template <class T> struct is_compound;

    // Const-volatile properties and transformations:
    template <class T> struct is_const;
    template <class T> struct is_volatile;
    template <class T> struct remove_const;
    template <class T> struct remove_volatile;
    template <class T> struct remove_cv;
    template <class T> struct add_const;
    template <class T> struct add_volatile;
    template <class T> struct add_cv;

    // Reference transformations:
    template <class T> struct remove_reference;
    template <class T> struct add_lvalue_reference;
    template <class T> struct add_rvalue_reference;

    // Pointer transformations:
    template <class T> struct remove_pointer;
    template <class T> struct add_pointer;

    template<class T> struct type_identity;                     // C++20
    template<class T>
      using type_identity_t = typename type_identity<T>::type;  // C++20

    // Integral properties:
    template <class T> struct is_signed;
    template <class T> struct is_unsigned;
    template <class T> struct make_signed;
    template <class T> struct make_unsigned;

    // Array properties and transformations:
    template <class T> struct rank;
    template <class T, unsigned I = 0> struct extent;
    template <class T> struct remove_extent;
    template <class T> struct remove_all_extents;

    template <class T> struct is_bounded_array;                 // C++20
    template <class T> struct is_unbounded_array;               // C++20

    // Member introspection:
    template <class T> struct is_pod;
    template <class T> struct is_trivial;
    template <class T> struct is_trivially_copyable;
    template <class T> struct is_standard_layout;
    template <class T> struct is_literal_type;
    template <class T> struct is_empty;
    template <class T> struct is_polymorphic;
    template <class T> struct is_abstract;
    template <class T> struct is_final; // C++14
    template <class T> struct is_aggregate; // C++17

    template <class T, class... Args> struct is_constructible;
    template <class T>                struct is_default_constructible;
    template <class T>                struct is_copy_constructible;
    template <class T>                struct is_move_constructible;
    template <class T, class U>       struct is_assignable;
    template <class T>                struct is_copy_assignable;
    template <class T>                struct is_move_assignable;
    template <class T, class U>       struct is_swappable_with;       // C++17
    template <class T>                struct is_swappable;            // C++17
    template <class T>                struct is_destructible;

    template <class T, class... Args> struct is_trivially_constructible;
    template <class T>                struct is_trivially_default_constructible;
    template <class T>                struct is_trivially_copy_constructible;
    template <class T>                struct is_trivially_move_constructible;
    template <class T, class U>       struct is_trivially_assignable;
    template <class T>                struct is_trivially_copy_assignable;
    template <class T>                struct is_trivially_move_assignable;
    template <class T>                struct is_trivially_destructible;

    template <class T, class... Args> struct is_nothrow_constructible;
    template <class T>                struct is_nothrow_default_constructible;
    template <class T>                struct is_nothrow_copy_constructible;
    template <class T>                struct is_nothrow_move_constructible;
    template <class T, class U>       struct is_nothrow_assignable;
    template <class T>                struct is_nothrow_copy_assignable;
    template <class T>                struct is_nothrow_move_assignable;
    template <class T, class U>       struct is_nothrow_swappable_with; // C++17
    template <class T>                struct is_nothrow_swappable;      // C++17
    template <class T>                struct is_nothrow_destructible;

    template <class T> struct has_virtual_destructor;

    template<class T> struct has_unique_object_representations;         // C++17

    // Relationships between types:
    template <class T, class U> struct is_same;
    template <class Base, class Derived> struct is_base_of;

    template <class From, class To> struct is_convertible;
    template <typename From, typename To> struct is_nothrow_convertible;                  // C++20
    template <typename From, typename To> inline constexpr bool is_nothrow_convertible_v; // C++20

    template <class Fn, class... ArgTypes> struct is_invocable;
    template <class R, class Fn, class... ArgTypes> struct is_invocable_r;

    template <class Fn, class... ArgTypes> struct is_nothrow_invocable;
    template <class R, class Fn, class... ArgTypes> struct is_nothrow_invocable_r;

    // Alignment properties and transformations:
    template <class T> struct alignment_of;
    template <size_t Len, size_t Align = most_stringent_alignment_requirement>
        struct aligned_storage;
    template <size_t Len, class... Types> struct aligned_union;
    template <class T> struct remove_cvref; // C++20

    template <class T> struct decay;
    template <class... T> struct common_type;
    template <class T> struct underlying_type;
    template <class> class result_of; // undefined
    template <class Fn, class... ArgTypes> class result_of<Fn(ArgTypes...)>;
    template <class Fn, class... ArgTypes> struct invoke_result;  // C++17

    // const-volatile modifications:
    template <class T>
      using remove_const_t    = typename remove_const<T>::type;  // C++14
    template <class T>
      using remove_volatile_t = typename remove_volatile<T>::type;  // C++14
    template <class T>
      using remove_cv_t       = typename remove_cv<T>::type;  // C++14
    template <class T>
      using add_const_t       = typename add_const<T>::type;  // C++14
    template <class T>
      using add_volatile_t    = typename add_volatile<T>::type;  // C++14
    template <class T>
      using add_cv_t          = typename add_cv<T>::type;  // C++14

    // reference modifications:
    template <class T>
      using remove_reference_t     = typename remove_reference<T>::type;  // C++14
    template <class T>
      using add_lvalue_reference_t = typename add_lvalue_reference<T>::type;  // C++14
    template <class T>
      using add_rvalue_reference_t = typename add_rvalue_reference<T>::type;  // C++14

    // sign modifications:
    template <class T>
      using make_signed_t   = typename make_signed<T>::type;  // C++14
    template <class T>
      using make_unsigned_t = typename make_unsigned<T>::type;  // C++14

    // array modifications:
    template <class T>
      using remove_extent_t      = typename remove_extent<T>::type;  // C++14
    template <class T>
      using remove_all_extents_t = typename remove_all_extents<T>::type;  // C++14

    template <class T>
      inline constexpr bool is_bounded_array_v
        = is_bounded_array<T>::value;                                     // C++20
      inline constexpr bool is_unbounded_array_v
        = is_unbounded_array<T>::value;                                   // C++20

    // pointer modifications:
    template <class T>
      using remove_pointer_t = typename remove_pointer<T>::type;  // C++14
    template <class T>
      using add_pointer_t    = typename add_pointer<T>::type;  // C++14

    // other transformations:
    template <size_t Len, std::size_t Align=default-alignment>
      using aligned_storage_t = typename aligned_storage<Len,Align>::type;  // C++14
    template <std::size_t Len, class... Types>
      using aligned_union_t   = typename aligned_union<Len,Types...>::type;  // C++14
    template <class T>
      using remove_cvref_t    = typename remove_cvref<T>::type;  // C++20
    template <class T>
      using decay_t           = typename decay<T>::type;  // C++14
    template <bool b, class T=void>
      using enable_if_t       = typename enable_if<b,T>::type;  // C++14
    template <bool b, class T, class F>
      using conditional_t     = typename conditional<b,T,F>::type;  // C++14
    template <class... T>
      using common_type_t     = typename common_type<T...>::type;  // C++14
    template <class T>
      using underlying_type_t = typename underlying_type<T>::type;  // C++14
    template <class T>
      using result_of_t       = typename result_of<T>::type;  // C++14
    template <class Fn, class... ArgTypes>
      using invoke_result_t   = typename invoke_result<Fn, ArgTypes...>::type;  // C++17

    template <class...>
      using void_t = void;   // C++17

      // See C++14 20.10.4.1, primary type categories
      template <class T> inline constexpr bool is_void_v
        = is_void<T>::value;                                             // C++17
      template <class T> inline constexpr bool is_null_pointer_v
        = is_null_pointer<T>::value;                                     // C++17
      template <class T> inline constexpr bool is_integral_v
        = is_integral<T>::value;                                         // C++17
      template <class T> inline constexpr bool is_floating_point_v
        = is_floating_point<T>::value;                                   // C++17
      template <class T> inline constexpr bool is_array_v
        = is_array<T>::value;                                            // C++17
      template <class T> inline constexpr bool is_pointer_v
        = is_pointer<T>::value;                                          // C++17
      template <class T> inline constexpr bool is_lvalue_reference_v
        = is_lvalue_reference<T>::value;                                 // C++17
      template <class T> inline constexpr bool is_rvalue_reference_v
        = is_rvalue_reference<T>::value;                                 // C++17
      template <class T> inline constexpr bool is_member_object_pointer_v
        = is_member_object_pointer<T>::value;                            // C++17
      template <class T> inline constexpr bool is_member_function_pointer_v
        = is_member_function_pointer<T>::value;                          // C++17
      template <class T> inline constexpr bool is_enum_v
        = is_enum<T>::value;                                             // C++17
      template <class T> inline constexpr bool is_union_v
        = is_union<T>::value;                                            // C++17
      template <class T> inline constexpr bool is_class_v
        = is_class<T>::value;                                            // C++17
      template <class T> inline constexpr bool is_function_v
        = is_function<T>::value;                                         // C++17

      // See C++14 20.10.4.2, composite type categories
      template <class T> inline constexpr bool is_reference_v
        = is_reference<T>::value;                                        // C++17
      template <class T> inline constexpr bool is_arithmetic_v
        = is_arithmetic<T>::value;                                       // C++17
      template <class T> inline constexpr bool is_fundamental_v
        = is_fundamental<T>::value;                                      // C++17
      template <class T> inline constexpr bool is_object_v
        = is_object<T>::value;                                           // C++17
      template <class T> inline constexpr bool is_scalar_v
        = is_scalar<T>::value;                                           // C++17
      template <class T> inline constexpr bool is_compound_v
        = is_compound<T>::value;                                         // C++17
      template <class T> inline constexpr bool is_member_pointer_v
        = is_member_pointer<T>::value;                                   // C++17

      // See C++14 20.10.4.3, type properties
      template <class T> inline constexpr bool is_const_v
        = is_const<T>::value;                                            // C++17
      template <class T> inline constexpr bool is_volatile_v
        = is_volatile<T>::value;                                         // C++17
      template <class T> inline constexpr bool is_trivial_v
        = is_trivial<T>::value;                                          // C++17
      template <class T> inline constexpr bool is_trivially_copyable_v
        = is_trivially_copyable<T>::value;                               // C++17
      template <class T> inline constexpr bool is_standard_layout_v
        = is_standard_layout<T>::value;                                  // C++17
      template <class T> inline constexpr bool is_pod_v
        = is_pod<T>::value;                                              // C++17
      template <class T> inline constexpr bool is_literal_type_v
        = is_literal_type<T>::value;                                     // C++17
      template <class T> inline constexpr bool is_empty_v
        = is_empty<T>::value;                                            // C++17
      template <class T> inline constexpr bool is_polymorphic_v
        = is_polymorphic<T>::value;                                      // C++17
      template <class T> inline constexpr bool is_abstract_v
        = is_abstract<T>::value;                                         // C++17
      template <class T> inline constexpr bool is_final_v
        = is_final<T>::value;                                            // C++17
      template <class T> inline constexpr bool is_aggregate_v
        = is_aggregate<T>::value;                                        // C++17
      template <class T> inline constexpr bool is_signed_v
        = is_signed<T>::value;                                           // C++17
      template <class T> inline constexpr bool is_unsigned_v
        = is_unsigned<T>::value;                                         // C++17
      template <class T, class... Args> inline constexpr bool is_constructible_v
        = is_constructible<T, Args...>::value;                           // C++17
      template <class T> inline constexpr bool is_default_constructible_v
        = is_default_constructible<T>::value;                            // C++17
      template <class T> inline constexpr bool is_copy_constructible_v
        = is_copy_constructible<T>::value;                               // C++17
      template <class T> inline constexpr bool is_move_constructible_v
        = is_move_constructible<T>::value;                               // C++17
      template <class T, class U> inline constexpr bool is_assignable_v
        = is_assignable<T, U>::value;                                    // C++17
      template <class T> inline constexpr bool is_copy_assignable_v
        = is_copy_assignable<T>::value;                                  // C++17
      template <class T> inline constexpr bool is_move_assignable_v
        = is_move_assignable<T>::value;                                  // C++17
      template <class T, class U> inline constexpr bool is_swappable_with_v
        = is_swappable_with<T, U>::value;                                // C++17
      template <class T> inline constexpr bool is_swappable_v
        = is_swappable<T>::value;                                        // C++17
      template <class T> inline constexpr bool is_destructible_v
        = is_destructible<T>::value;                                     // C++17
      template <class T, class... Args> inline constexpr bool is_trivially_constructible_v
        = is_trivially_constructible<T, Args...>::value;                 // C++17
      template <class T> inline constexpr bool is_trivially_default_constructible_v
        = is_trivially_default_constructible<T>::value;                  // C++17
      template <class T> inline constexpr bool is_trivially_copy_constructible_v
        = is_trivially_copy_constructible<T>::value;                     // C++17
      template <class T> inline constexpr bool is_trivially_move_constructible_v
        = is_trivially_move_constructible<T>::value;                     // C++17
      template <class T, class U> inline constexpr bool is_trivially_assignable_v
        = is_trivially_assignable<T, U>::value;                          // C++17
      template <class T> inline constexpr bool is_trivially_copy_assignable_v
        = is_trivially_copy_assignable<T>::value;                        // C++17
      template <class T> inline constexpr bool is_trivially_move_assignable_v
        = is_trivially_move_assignable<T>::value;                        // C++17
      template <class T> inline constexpr bool is_trivially_destructible_v
        = is_trivially_destructible<T>::value;                           // C++17
      template <class T, class... Args> inline constexpr bool is_nothrow_constructible_v
        = is_nothrow_constructible<T, Args...>::value;                   // C++17
      template <class T> inline constexpr bool is_nothrow_default_constructible_v
        = is_nothrow_default_constructible<T>::value;                    // C++17
      template <class T> inline constexpr bool is_nothrow_copy_constructible_v
        = is_nothrow_copy_constructible<T>::value;                       // C++17
      template <class T> inline constexpr bool is_nothrow_move_constructible_v
        = is_nothrow_move_constructible<T>::value;                       // C++17
      template <class T, class U> inline constexpr bool is_nothrow_assignable_v
        = is_nothrow_assignable<T, U>::value;                            // C++17
      template <class T> inline constexpr bool is_nothrow_copy_assignable_v
        = is_nothrow_copy_assignable<T>::value;                          // C++17
      template <class T> inline constexpr bool is_nothrow_move_assignable_v
        = is_nothrow_move_assignable<T>::value;                          // C++17
      template <class T, class U> inline constexpr bool is_nothrow_swappable_with_v
        = is_nothrow_swappable_with<T, U>::value;                       // C++17
      template <class T> inline constexpr bool is_nothrow_swappable_v
        = is_nothrow_swappable<T>::value;                               // C++17
      template <class T> inline constexpr bool is_nothrow_destructible_v
        = is_nothrow_destructible<T>::value;                             // C++17
      template <class T> inline constexpr bool has_virtual_destructor_v
        = has_virtual_destructor<T>::value;                              // C++17
      template<class T> inline constexpr bool has_unique_object_representations_v // C++17
        = has_unique_object_representations<T>::value;

      // See C++14 20.10.5, type property queries
      template <class T> inline constexpr size_t alignment_of_v
        = alignment_of<T>::value;                                        // C++17
      template <class T> inline constexpr size_t rank_v
        = rank<T>::value;                                                // C++17
      template <class T, unsigned I = 0> inline constexpr size_t extent_v
        = extent<T, I>::value;                                           // C++17

      // See C++14 20.10.6, type relations
      template <class T, class U> inline constexpr bool is_same_v
        = is_same<T, U>::value;                                          // C++17
      template <class Base, class Derived> inline constexpr bool is_base_of_v
        = is_base_of<Base, Derived>::value;                              // C++17
      template <class From, class To> inline constexpr bool is_convertible_v
        = is_convertible<From, To>::value;                               // C++17
      template <class Fn, class... ArgTypes> inline constexpr bool is_invocable_v
        = is_invocable<Fn, ArgTypes...>::value;                          // C++17
      template <class R, class Fn, class... ArgTypes> inline constexpr bool is_invocable_r_v
        = is_invocable_r<R, Fn, ArgTypes...>::value;                     // C++17
      template <class Fn, class... ArgTypes> inline constexpr bool is_nothrow_invocable_v
        = is_nothrow_invocable<Fn, ArgTypes...>::value;                  // C++17
      template <class R, class Fn, class... ArgTypes> inline constexpr bool is_nothrow_invocable_r_v
        = is_nothrow_invocable_r<R, Fn, ArgTypes...>::value;             // C++17

      // [meta.logical], logical operator traits:
      template<class... B> struct conjunction;                           // C++17
      template<class... B>
        inline constexpr bool conjunction_v = conjunction<B...>::value;  // C++17
      template<class... B> struct disjunction;                           // C++17
      template<class... B>
        inline constexpr bool disjunction_v = disjunction<B...>::value;  // C++17
      template<class B> struct negation;                                 // C++17
      template<class B>
        inline constexpr bool negation_v = negation<B>::value;           // C++17

}

*/
#ifndef __cuda_std__
#include <__config>
#else
#ifndef _LIBCUDACXX_COMPILER_NVRTC
#include <type_traits>
#endif // _LIBCUDACXX_COMPILER_NVRTC
#endif // __cuda_std__

#include "__assert" // all public C++ headers provide the assertion handler
#include "__functional/identity.h"
#include "__functional/invoke.h"
#include "__memory/addressof.h"
#include "__type_traits/add_const.h"
#include "__type_traits/add_cv.h"
#include "__type_traits/add_lvalue_reference.h"
#include "__type_traits/add_pointer.h"
#include "__type_traits/add_rvalue_reference.h"
#include "__type_traits/add_volatile.h"
#include "__type_traits/aligned_storage.h"
#include "__type_traits/aligned_union.h"
#include "__type_traits/alignment_of.h"
#include "__type_traits/apply_cv.h"
#include "__type_traits/can_extract_key.h"
#include "__type_traits/common_reference.h"
#include "__type_traits/common_type.h"
#include "__type_traits/conditional.h"
#include "__type_traits/conjunction.h"
#include "__type_traits/copy_cv.h"
#include "__type_traits/copy_cvref.h"
#include "__type_traits/decay.h"
#include "__type_traits/dependent_type.h"
#include "__type_traits/disjunction.h"
#include "__type_traits/enable_if.h"
#include "__type_traits/extent.h"
#include "__type_traits/has_unique_object_representation.h"
#include "__type_traits/has_virtual_destructor.h"
#include "__type_traits/integral_constant.h"
#include "__type_traits/is_abstract.h"
#include "__type_traits/is_aggregate.h"
#include "__type_traits/is_allocator.h"
#include "__type_traits/is_arithmetic.h"
#include "__type_traits/is_array.h"
#include "__type_traits/is_assignable.h"
#include "__type_traits/is_base_of.h"
#include "__type_traits/is_bounded_array.h"
#include "__type_traits/is_callable.h"
#include "__type_traits/is_char_like_type.h"
#include "__type_traits/is_class.h"
#include "__type_traits/is_compound.h"
#include "__type_traits/is_const.h"
#include "__type_traits/is_constant_evaluated.h"
#include "__type_traits/is_constructible.h"
#include "__type_traits/is_convertible.h"
#include "__type_traits/is_copy_assignable.h"
#include "__type_traits/is_copy_constructible.h"
#include "__type_traits/is_core_convertible.h"
#include "__type_traits/is_default_constructible.h"
#include "__type_traits/is_destructible.h"
#include "__type_traits/is_empty.h"
#include "__type_traits/is_enum.h"
#include "__type_traits/is_final.h"
#include "__type_traits/is_floating_point.h"
#include "__type_traits/is_function.h"
#include "__type_traits/is_fundamental.h"
#include "__type_traits/is_implicitly_default_constructible.h"
#include "__type_traits/is_integral.h"
#include "__type_traits/is_literal_type.h"
#include "__type_traits/is_member_function_pointer.h"
#include "__type_traits/is_member_object_pointer.h"
#include "__type_traits/is_member_pointer.h"
#include "__type_traits/is_move_assignable.h"
#include "__type_traits/is_move_constructible.h"
#include "__type_traits/is_nothrow_assignable.h"
#include "__type_traits/is_nothrow_constructible.h"
#include "__type_traits/is_nothrow_convertible.h"
#include "__type_traits/is_nothrow_copy_assignable.h"
#include "__type_traits/is_nothrow_copy_constructible.h"
#include "__type_traits/is_nothrow_default_constructible.h"
#include "__type_traits/is_nothrow_destructible.h"
#include "__type_traits/is_nothrow_move_assignable.h"
#include "__type_traits/is_nothrow_move_constructible.h"
#include "__type_traits/is_null_pointer.h"
#include "__type_traits/is_object.h"
#include "__type_traits/is_pod.h"
#include "__type_traits/is_pointer.h"
#include "__type_traits/is_polymorphic.h"
#include "__type_traits/is_primary_template.h"
#include "__type_traits/is_reference_wrapper.h"
#include "__type_traits/is_reference.h"
#include "__type_traits/is_referenceable.h"
#include "__type_traits/is_same.h"
#include "__type_traits/is_scalar.h"
#include "__type_traits/is_scoped_enum.h"
#include "__type_traits/is_signed_integer.h"
#include "__type_traits/is_signed.h"
#include "__type_traits/is_standard_layout.h"
#include "__type_traits/is_swappable.h"
#include "__type_traits/is_trivial.h"
#include "__type_traits/is_trivially_assignable.h"
#include "__type_traits/is_trivially_constructible.h"
#include "__type_traits/is_trivially_copy_assignable.h"
#include "__type_traits/is_trivially_copy_constructible.h"
#include "__type_traits/is_trivially_copyable.h"
#include "__type_traits/is_trivially_default_constructible.h"
#include "__type_traits/is_trivially_destructible.h"
#include "__type_traits/is_trivially_move_assignable.h"
#include "__type_traits/is_trivially_move_constructible.h"
#include "__type_traits/is_unbounded_array.h"
#include "__type_traits/is_union.h"
#include "__type_traits/is_unsigned_integer.h"
#include "__type_traits/is_unsigned.h"
#include "__type_traits/is_valid_expansion.h"
#include "__type_traits/is_void.h"
#include "__type_traits/is_volatile.h"
#include "__type_traits/lazy.h"
#include "__type_traits/make_const_lvalue_ref.h"
#include "__type_traits/make_32_64_or_128_bit.h"
#include "__type_traits/make_signed.h"
#include "__type_traits/make_unsigned.h"
#include "__type_traits/maybe_const.h"
#include "__type_traits/nat.h"
#include "__type_traits/negation.h"
#include "__type_traits/promote.h"
#include "__type_traits/rank.h"
#include "__type_traits/remove_all_extents.h"
#include "__type_traits/remove_const_ref.h"
#include "__type_traits/remove_const.h"
#include "__type_traits/remove_cvref.h"
#include "__type_traits/remove_cv.h"
#include "__type_traits/remove_extent.h"
#include "__type_traits/remove_pointer.h"
#include "__type_traits/remove_reference.h"
#include "__type_traits/remove_volatile.h"
#include "__type_traits/result_of.h"
#include "__type_traits/type_identity.h"
#include "__type_traits/type_list.h"
#include "__type_traits/underlying_type.h"
#include "__type_traits/void_t.h"
#include "__utility/convert_to_integral.h"
#include "__utility/declval.h"
#include "__utility/forward.h"
#include "__utility/move.h"
#include "__utility/swap.h"
#include "cstdint"
#include "cstddef"
#include "version"

#if defined(_LIBCUDACXX_USE_PRAGMA_GCC_SYSTEM_HEADER)
#pragma GCC system_header
#endif

_LIBCUDACXX_BEGIN_NAMESPACE_STD

template <class _T1, class _T2> struct _LIBCUDACXX_TEMPLATE_VIS pair;
template <class _Tp> class _LIBCUDACXX_TEMPLATE_VIS reference_wrapper;
template <class _Tp> struct _LIBCUDACXX_TEMPLATE_VIS hash;

template <bool> struct _MetaBase;
template <>
struct _MetaBase<true> {
  template <class _Tp, class _Up>
  using _SelectImpl _LIBCUDACXX_NODEBUG_TYPE = _Tp;
  template <template <class...> class _FirstFn, template <class...> class, class ..._Args>
  using _SelectApplyImpl _LIBCUDACXX_NODEBUG_TYPE = _FirstFn<_Args...>;
  template <class _First, class...>
  using _FirstImpl _LIBCUDACXX_NODEBUG_TYPE = _First;
  template <class, class _Second, class...>
  using _SecondImpl _LIBCUDACXX_NODEBUG_TYPE = _Second;
  template <class _Tp = void>
  using _EnableIfImpl _LIBCUDACXX_NODEBUG_TYPE = _Tp;
  template <class _Result, class _First, class ..._Rest>
  using _OrImpl _LIBCUDACXX_NODEBUG_TYPE = typename _MetaBase<_First::value != true && sizeof...(_Rest) != 0>::template _OrImpl<_First, _Rest...>;
  template <class _Result, class _First, class ..._Rest>
  using _AndImpl _LIBCUDACXX_NODEBUG_TYPE = typename _MetaBase<_First::value == true && sizeof...(_Rest) != 0>::template _AndImpl<_First, _Rest...>;
};

template <>
struct _MetaBase<false> {
  template <class _Tp, class _Up>
  using _SelectImpl _LIBCUDACXX_NODEBUG_TYPE = _Up;
  template <template <class...> class, template <class...> class _SecondFn, class ..._Args>
  using _SelectApplyImpl _LIBCUDACXX_NODEBUG_TYPE = _SecondFn<_Args...>;
  template <class _Result, class ...>
  using _OrImpl _LIBCUDACXX_NODEBUG_TYPE = _Result;
  template <class _Result, class ...>
  using _AndImpl _LIBCUDACXX_NODEBUG_TYPE = _Result;
};
template <bool _Cond, class _Ret = void>
using _EnableIf _LIBCUDACXX_NODEBUG_TYPE = typename _MetaBase<_Cond>::template _EnableIfImpl<_Ret>;
template <class ..._Args>
using _FirstType _LIBCUDACXX_NODEBUG_TYPE = typename _MetaBase<(sizeof...(_Args) >= 1)>::template _FirstImpl<_Args...>;
template <class ..._Args>
using _SecondType _LIBCUDACXX_NODEBUG_TYPE = typename _MetaBase<(sizeof...(_Args) >= 2)>::template _SecondImpl<_Args...>;

// helper class:

template <class _Tp>
inline _LIBCUDACXX_INLINE_VISIBILITY
__decay_t<_Tp> __decay_copy(_Tp&& __t)
{
    return _CUDA_VSTD::forward<_Tp>(__t);
}

// iter_swap

template <class _ForwardIterator1, class _ForwardIterator2>
inline _LIBCUDACXX_INLINE_VISIBILITY _LIBCUDACXX_CONSTEXPR_AFTER_CXX17
void
iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b)
    //                                  _NOEXCEPT_(_NOEXCEPT_(swap(*__a, *__b)))
               _NOEXCEPT_(_NOEXCEPT_(swap(*_CUDA_VSTD::declval<_ForwardIterator1>(),
                                          *_CUDA_VSTD::declval<_ForwardIterator2>())))
{
    swap(*__a, *__b);
}

#ifndef _LIBCUDACXX_CXX03_LANG

template <class _Tp>
struct __has_operator_addressof_member_imp
{
    template <class _Up>
        _LIBCUDACXX_INLINE_VISIBILITY
        static auto __test(int)
            -> typename __select_2nd<decltype(_CUDA_VSTD::declval<_Up>().operator&()), true_type>::type;
    template <class>
        _LIBCUDACXX_INLINE_VISIBILITY
        static auto __test(long) -> false_type;

    static const bool value = decltype(__test<_Tp>(0))::value;
};

template <class _Tp>
struct __has_operator_addressof_free_imp
{
    template <class _Up>
        _LIBCUDACXX_INLINE_VISIBILITY
        static auto __test(int)
            -> typename __select_2nd<decltype(operator&(_CUDA_VSTD::declval<_Up>())), true_type>::type;
    template <class>
        _LIBCUDACXX_INLINE_VISIBILITY
        static auto __test(long) -> false_type;

    static const bool value = decltype(__test<_Tp>(0))::value;
};

template <class _Tp>
struct __has_operator_addressof
    : public integral_constant<bool, __has_operator_addressof_member_imp<_Tp>::value
                                  || __has_operator_addressof_free_imp<_Tp>::value>
{};

#endif  // _LIBCUDACXX_CXX03_LANG

_LIBCUDACXX_END_NAMESPACE_STD

#endif  // _LIBCUDACXX_TYPE_TRAITS
